package com.infore.authorityManagement.service.impl;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;

import org.apache.commons.lang.StringUtils;
import org.hibernate.HibernateException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.infore.authorityManagement.entity.BusinessConstant;
import com.infore.authorityManagement.entity.CurrentUserInfo;
import com.infore.authorityManagement.entity.PasswordVo;
import com.infore.authorityManagement.entity.SysRole;
import com.infore.authorityManagement.entity.SysUser;
import com.infore.authorityManagement.entity.UserLoginInfo;
import com.infore.authorityManagement.repository.ICurrentUserInfoRepository;
import com.infore.authorityManagement.repository.ISysUserRepository;
import com.infore.authorityManagement.repository.IUserLoginInfoRepository;
import com.infore.authorityManagement.service.ISysRoleService;
import com.infore.authorityManagement.service.ISysUserService;
import com.infore.authorityManagement.util.Page;
import com.infore.authorityManagement.util.PageUtil;
import com.infore.authorityManagement.util.UUIDGenerator;

@Service
@Transactional
public class SysUserServiceImpl implements ISysUserService {
    
    //@Value("${sessionOrRedis}")
    private String sessionOrRedis = "session";
   // @Value("${timeout-value}")
    private int timeoutValue =20;
    
    @Autowired
    ISysUserRepository sysUserRepository;
    
    @Autowired
    ICurrentUserInfoRepository currentUserInfoRepository;
    
    @Autowired
    ISysRoleService roleService;
    
    @Autowired
    IUserLoginInfoRepository userLoginInfoRepository;
    
    @Override
    public List<SysUser> getUsers(SysUser sysUser) {
        Specification<SysUser> specification = this.createSpecification(sysUser);
        return sysUserRepository.findAll(specification);
    }

    private Specification<SysUser> createSpecification(SysUser sysUser) {
        Specification<SysUser> specification = new Specification<SysUser>() {
            @Override
            public Predicate toPredicate(Root<SysUser> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>();
                if (!StringUtils.isBlank(sysUser.getUserId())) {
                    predicates.add(cb.equal(root.get("userId"), sysUser.getUserId()));
                }
                if (sysUser.getUserType() != null) {
                    predicates.add(cb.equal(root.get("userType"), sysUser.getUserType()));
                }
                if (!StringUtils.isBlank(sysUser.getUserAccount())) {
                    predicates.add(cb.like(root.get("userAccount"), "%"+sysUser.getUserAccount()+"%"));
                }
                if (!StringUtils.isBlank(sysUser.getUserName())) {
                    predicates.add(cb.like(root.get("userName"), "%"+sysUser.getUserName()+"%"));
                }
                if (!StringUtils.isBlank(sysUser.getEmail())) {
                    predicates.add(cb.like(root.get("email"), "%"+sysUser.getEmail()+"%"));
                }
                if (!StringUtils.isBlank(sysUser.getAreaId())) {
                    predicates.add(cb.like(root.get("areaId"), "%"+sysUser.getAreaId()+"%"));
                }
                Predicate[] p = new Predicate[predicates.size()];
                query.where(cb.and(predicates.toArray(p)));
                query.orderBy(cb.asc(root.get("serialNumber")));
                return query.getRestriction();
            }
        };
        return specification;
    }

    @Override
    public SysUser getUserById(String userId) {
        return sysUserRepository.findById(userId).orElse(null);
    }

    @Override
    public SysUser getUserByAccount(String userAccount) {
        return sysUserRepository.findByUserAccount(userAccount);
    }

    @Override
    public Page<SysUser> getUsersForPage(SysUser sysUser, Integer pageSize, Integer pageNo) {
        Specification<SysUser> specification = this.createSpecification(sysUser);
        PageRequest pageable = PageRequest.of(pageNo-1, pageSize);
        return PageUtil.pageConvert(sysUserRepository.findAll(specification, pageable));
    }

    @Override
    public Map<String, Object> addUser(SysUser sysUser) {
        Map<String, Object> map = new HashMap<String, Object>();
        SysUser u = this.getUserByAccount(sysUser.getUserAccount());
        int resultIdt = 0;
        if (u != null) {
            resultIdt = -1; // 该账号已经存在
            map.put("resultIdt", resultIdt);
            return map;
        }
        String id = UUIDGenerator.getUUID();
        //sysUser.setPassword(MD5Util.encode(sysUser.getPassword())); // 密码加密
        sysUser.setUserId(id);
        java.util.Date date = new java.util.Date();
        long d = date.getTime();
        Timestamp timestamp = new Timestamp(d);
        sysUser.setCreateTime(timestamp);
        if (sysUser.getRole() != null) {
            SysRole role = roleService.getRoleById(sysUser.getRole().getRoleId());
            sysUser.setRole(role);
        }
        try {
            sysUserRepository.saveAndFlush(sysUser);
        } catch (HibernateException ex) {
            resultIdt = -2; // 数据异常
        }
        map.put("resultIdt", resultIdt);
        map.put("userId", id);
        return map;
    
    }

    @Override
    public int deleteUserById(String userId) {
        int resultIdt = 0;
        try {
            sysUserRepository.deleteById(userId);
        } catch (Exception ex) {
            ex.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            resultIdt = -1;
        }
        return resultIdt;
    }

    @Override
    public int deleteUserByAccount(String userAccount) {
        int resultIdt = 0;
        try {
            sysUserRepository.delete(getUserByAccount(userAccount));
        } catch (Exception ex) {
            ex.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            resultIdt = -1;
        }
        return resultIdt;
    }

    @Override
    public int updateUser(SysUser sysUser) {

        SysUser u = getUserById(sysUser.getUserId());
        int resultIdt = 0;
        if (u == null) {
            return -1; // 该用户不存在
        }
        /*
         * if(getUserByAccount(sysUser.getUserAccount()) != null) { return -2; //账号已经存存在 }
         */
        if (sysUser.getAreaId() != null && !"".equals(sysUser.getAreaId())) {
            u.setAreaId(sysUser.getAreaId());
        }
        if (sysUser.getRole() != null) {
            SysRole role = roleService.getRoleById(sysUser.getRole().getRoleId());
            u.setRole(role);
        }
        if (sysUser.getUserName() != null && !"".equals(sysUser.getUserName())) {
            u.setUserName(sysUser.getUserName());
        }
        if (sysUser.getUserAccount() != null && !"".equals(sysUser.getUserAccount())) {
            u.setUserAccount(sysUser.getUserAccount());
        }
        if (sysUser.getPassword() != null && !"".equals(sysUser.getPassword())) {
           // u.setPassword(MD5Util.encode(sysUser.getPassword()));
            u.setPassword(sysUser.getPassword());
        }
        if (sysUser.getUserType() != null) {
            u.setUserType(sysUser.getUserType());
        } else {
            u.setUserType(0);   //默认设置为普通用户
        }
        if (sysUser.getEmail() != null && !"".equals(sysUser.getEmail())) {
            u.setEmail(sysUser.getEmail());
        }
        if (sysUser.getPhonenb() != null) {
            u.setPhonenb(sysUser.getPhonenb());
        }
        if (!StringUtils.isBlank(sysUser.getFixedTelphone())) {
            u.setFixedTelphone(sysUser.getFixedTelphone());
        }
        if (sysUser.getSex() != null) {
            u.setSex(sysUser.getSex());
        }
        if (sysUser.getImgurl() != null && !"".equals(sysUser.getImgurl())) {
            u.setImgurl(sysUser.getImgurl());
        }
        try {
            sysUserRepository.saveAndFlush(u);
        } catch (Exception ex) {
            ex.printStackTrace();
            resultIdt = -3;
        }
        return resultIdt;
    
    }


    @Override
    public int updateUserPassword(PasswordVo passwordVo) {

        SysUser user = getUserById(passwordVo.getUserId());
        if (user == null) {
            return -1; // 该用户不存在
        }
        String userPassword = user.getPassword();
        if (!userPassword.equals(passwordVo.getOldPassword())) {
            return -2;  //原密码错误
        }
        user.setPassword(passwordVo.getPassword());
        try {
            sysUserRepository.saveAndFlush(user);
        }catch (Exception ex) {
            ex.printStackTrace();
            return -3;
        }
        return 0;
    
    }

    @Override
    public Map<String, Object> userAuth(String account, String password, String appUUID, HttpServletRequest request) {
        Map<String, Object> map = new HashMap<String, Object>();
        SysUser sysUser = getUserByAccount(account);
        int resultIdt = 0;
        if (sysUser == null) {
            resultIdt = -1; // 账号不存在
            map.put("resultIdt", resultIdt);
            return map;
        }
        if (!sysUser.getPassword().equals(password)) {
            /*sysUser.setWrongpwdno(sysUser.getWrongpwdno() + 1);
            sysUser.setLoginTime(timestamp);
            sysUserDao.update(sysUser);*/
            resultIdt = -3; // 密码错误
            map.put("resultIdt", resultIdt);
            return map;
        }
        CurrentUserInfo currentUserInfo = null;
        if ("session".equals(sessionOrRedis)) {
            currentUserInfo = registerSession2Db(sysUser, appUUID);
        } else {
            //currentUserInfo = registerSession2Redis(sysUser, appUUID);
        }
        
        UserLoginInfo userLoginInfo = new UserLoginInfo();
        userLoginInfo.setId(UUIDGenerator.getUUID());
        userLoginInfo.setUserAccount(sysUser.getUserAccount());
        userLoginInfo.setUserName(sysUser.getUserName());
        userLoginInfo.setLoginTime(new Date());
        userLoginInfo.setIp(getRemoteHost(request));
        userLoginInfo.setLoginType(0);
        userLoginInfoRepository.saveAndFlush(userLoginInfo);
        map.put("resultIdt", resultIdt);
        map.put("userInfo", sysUser);
        map.put("token", currentUserInfo.getToken());
        return map;
    }
    
    private String getRemoteHost(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
            ip = request.getHeader("Proxy-Client-IP");
        }
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
            ip = request.getRemoteAddr();
        }
        /*if(ip.trim().contains(",")){      //因为经过多层代理后会有多个代理，取第一个ip地址就可以了
            String [] ips=ip.split(",");
            ip=ips[0];
        }*/
        return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;
    }

    private CurrentUserInfo registerSession2Db(SysUser sysUser, String appUUID) {
        CurrentUserInfo currentUserInfo = currentUserInfoRepository.findByUserAccount(sysUser.getUserAccount());
        // currentUserInfoDao.get("userAccount", sysUser.getUserAccount());

        // 携带手机标识id 则查询手机id不为空的当前用户，否则查询为空的当前用户 
        
//        List<CurrentUserInfo> list = currentUserInfoDao.getListByCriteria(criteria);
//        if (list.size() > 0) {
//            currentUserInfo = list.get(0);
//        }

        java.util.Date date = new java.util.Date();
        long d = date.getTime() + BusinessConstant.EFFECTIVE_TIME * 60 * 1000;
        Timestamp timestamp = new Timestamp(d);
        String token = UUIDGenerator.getUUID(); // 创建token
        if (currentUserInfo != null) {
            currentUserInfo.setToken(token);
            currentUserInfo.setAdmin(sysUser.getAdmin());
            if (appUUID != null) {
                currentUserInfo.setAppUUID(appUUID);
            }
            currentUserInfo.setIdentify(0); 
            currentUserInfo.setFailuretime(timestamp);
            currentUserInfoRepository.flush();
            return currentUserInfo;
        }
        // 用户第一次验证通过 新增用户认证信息
        currentUserInfo = new CurrentUserInfo();
        currentUserInfo.setCurrntId(UUIDGenerator.getUUID());
        currentUserInfo.setUserId(sysUser.getUserId());
        currentUserInfo.setToken(token);
        currentUserInfo.setUserAccount(sysUser.getUserAccount());
        currentUserInfo.setUserName(sysUser.getUserName());
        currentUserInfo.setIdentify(0);
        currentUserInfo.setEffectivetime(BusinessConstant.EFFECTIVE_TIME);
        currentUserInfo.setFailuretime(timestamp);
        currentUserInfo.setAdmin(sysUser.getAdmin());
        if (appUUID != null) {
            currentUserInfo.setAppUUID(appUUID);
        }
        currentUserInfoRepository.saveAndFlush(currentUserInfo);
        return currentUserInfo;
    }

    /***
     * 退出登录
     */
    public int logout(String token) {
        if (token == null || "".equals(token)) {
            return -1;
        }
        if ("session".equals(sessionOrRedis)) {
            CurrentUserInfo currentUserInfo = currentUserInfoRepository.findByToken(token);
            if (currentUserInfo == null) {
                return -2;
            }
            java.util.Date date = new java.util.Date();
            long d = date.getTime();
            Timestamp timestamp = new Timestamp(d - timeoutValue * 60000);
            currentUserInfo.setFailuretime(timestamp); // 设置失效时间
            currentUserInfo.setIdentify(1); // 设置标识无效
            currentUserInfoRepository.flush();
        } else {
           // redisUtils.remove(token); // 清除缓存
        }
        return 0;
    }
    
    @Override
    public int validateToken(String token) {
        if (token == null || "".equals(token)) {
            return -1;
        }
        CurrentUserInfo currentUserInfo = null;
        if ("session".equals(sessionOrRedis)) {
            currentUserInfo = currentUserInfoRepository.findByToken(token);
          
        } else {
           // redisUtils.remove(token); // 清除缓存
        }
        if (currentUserInfo == null) {
            return -2;
        }
        long f = currentUserInfo.getFailuretime().getTime();
        int identify = currentUserInfo.getIdentify();
        java.util.Date date = new java.util.Date();
        long d = date.getTime();
        if(identify == 1) {
            return -2;
        }
        if(d > f && identify == 0) {
            return -3; //超时失效
        }
        return 0;
        
    }

}
